#include "SysInfo.h"
#include <string.h>

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/rtc.h>
#include <unistd.h>


#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>

#include <list>



#include "SysHelper.h"

CSysInfo::CSysInfo()
{

    return ;
}

int CSysInfo::GetNetworkInfo(const std::string &strEthName, std::string &strMacAddr, 
                    std::string &strIpAddr, std::string &strNetMask, std::string &strGateWay)
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if (sockfd == -1)
    {
        printf("Failed to create socket.\n");
        return -1;
    }

    struct ifreq ifStu;
    memset(&ifStu, 0, sizeof(ifStu));
    strncpy(ifStu.ifr_name, strEthName.c_str(), IFNAMSIZ);


    // MacAddr
    ioctl(sockfd, SIOCGIFHWADDR, &ifStu);
    char szMacAddr[50];
    
    sprintf(szMacAddr, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)ifStu.ifr_hwaddr.sa_data[0], (unsigned char)ifStu.ifr_hwaddr.sa_data[1], 
                                                        (unsigned char)ifStu.ifr_hwaddr.sa_data[2], (unsigned char)ifStu.ifr_hwaddr.sa_data[3], 
                                                        (unsigned char)ifStu.ifr_hwaddr.sa_data[4], (unsigned char)ifStu.ifr_hwaddr.sa_data[5]); 

    // printf("MacAddr %s\n",szMacAddr);  
    strMacAddr = szMacAddr;

    // IPAddr
    ioctl(sockfd, SIOCGIFADDR, &ifStu);
    // printf("inet %s\n",inet_ntoa(((struct sockaddr_in *)&ifStu.ifr_addr)->sin_addr));  
    strIpAddr = inet_ntoa(((struct sockaddr_in *)&ifStu.ifr_addr)->sin_addr);

    // NetMask
    ioctl(sockfd, SIOCGIFNETMASK, &ifStu);
    // printf("netmask %s\n",inet_ntoa(((struct sockaddr_in *)&ifStu.ifr_addr)->sin_addr));
    strNetMask = inet_ntoa(((struct sockaddr_in *)&ifStu.ifr_addr)->sin_addr);
    
    close(sockfd);

    // GateWay
    std::string strCmd = "ip route show default | awk '/default/ {print $3}'";
    CSysHelper::GetShellReturn(strCmd, strGateWay);

    if(strGateWay.back() == '\n')
        strGateWay.pop_back();
    // printf("GateWay %s\n", strGateWay.c_str());

    return 0;
    
}


void CSysInfo::GetDevName(char buf[],int bufsize)
{
    gethostname(buf,bufsize);
}


void CSysInfo::GetCurrFreq(char freqBuf[],int bufsize)
{
    char Buf[10];
    #define CPU_CURR_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq"
    if(access(CPU_CURR_FREQ_FILE,F_OK) == 0)
    {
        FILE* fp = fopen(CPU_CURR_FREQ_FILE,"r");
        fread(freqBuf,1,bufsize,fp);
        fclose(fp);
    }
    else
    {
        printf("access() error\n");
        strncpy(freqBuf,"",bufsize);
    }

    return ;
}

bool CSysInfo::GetVersion(std::string &strGitVersion, std::string &strGitBranch)
{
    // 需要转换一下才能赋值给String对象
    const char* versionValue = GIT_VERSION;
    strGitVersion = versionValue;

    const char* branchValue = GIT_BRANCH;
    strGitBranch = branchValue;

    return true;
}

bool CSysInfo::GetCompileDateTime(std::string &strCompileDate, std::string &strCompileTime)
{
    strCompileDate = __DATE__;
    strCompileTime = __TIME__;
    return true;
}


bool CSysInfo::GetRtcTime(std::string &strRtcTime)
{
    std::string strRtc;
    int ret = CSysHelper::GetShellReturn("hwclock -r", strRtc);
    
    // TBD
    strRtcTime = strRtc;

    return ret;
}
bool CSysInfo::GetRtcDate(std::string &strDateTime)
{
    strDateTime = "Not finish";
    return true;
}

bool CSysInfo::GetSystemTime(std::string &strSysTime)
{
    int ret = CSysHelper::GetShellReturn("date", strSysTime);

    return ret;
}
bool CSysInfo::GetSystemDate(std::string &strSysDate)
{
    int rtcFd = open("/dev/rtc",O_RDONLY);
    struct rtc_time rtc_tm;
    ioctl(rtcFd, RTC_RD_TIME, &rtc_tm);

    printf("GetSystemDate() ------ %2d:%2d:%2d\n", rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);

    // int ret = CSysHelper::GetShellReturn("date", strSysDate);

    // return ret;
}

bool CSysInfo::SetSystemTime(const std::string &strSetTime, bool bSetRtc)
{
	return true;
}
bool CSysInfo::SetSystemDate(const std::string &strSetTime, bool bSetRtc)
{
	return true;
}

